#!/usr/bin/env python

import sys
import datetime
import argparse
import subprocess
import os


parser= argparse.ArgumentParser(description= """ """, formatter_class= argparse.RawTextHelpFormatter)

parser.add_argument("--server", '-s', type= str, required= True,
    help= """Name of the server to back up. E.g. 'uk-cri-lcst01'.
This string passed to ssh and rsync

""")

parser.add_argument("--rootpath", '-r', type= str, required= True,
    help= """Root path on `--server` to back up. Stuff contained under this
path will be backed up. E.g. '/lustre/sblab/berald01/' or '/home/berald01/'

""")

parser.add_argument("--exclude", '-x', type= str, required= False, nargs= '+',
    help= """One or more paths under --rootpath which should not be backed-up.
This list of paths passed to `rsync --exclude`.
E.g. use `--rootpath /lustre/sblab/berald01/ --exclude Tritume`
to skip the dir /lustre/sblab/berald01/Tritume

""")

parser.add_argument("--archive", '-a', type= str, required= False,
    default= 'cri\\\\berald01@uk-cri-larc01.cri.camres.org',
    help= """Host name of the archive server (where backup will go).
This arg passed to `getArchiveDir.py --address`. 

""")

parser.add_argument("--archivePath", '-p', type= str, required= False,
    default= "/ArchiveDataFS2/Groups/sblab",
    help= """Path on the archive server where backup will go.
This arg passed to `getArchiveDir.py --basepath`. Default /ArchiveDataFS1/Groups/sblab
MEMO: Backup data will not go straight to this path as getArchiveDir.py will look
for the last writable quarter, so back up will go to something like
"/ArchiveDataFS1/Groups/sblab/2013-Q1"

""")

parser.add_argument("--email", '-e', type= str, required= False,
    help= """Email log file to this address. If not supplied email will not be sent

""")

parser.add_argument("--log", '-l', type= str, required= False,
    default= None,
    help= """Directory to write the rsync log. This directory will be created
on the server to be backed-up.
*Include full path and make sure you can write there.* Default <--roothpath>/rsync_log/
In this dir a file named `YYYYMMDD-H-M-S`.rsync.log will be created.
""")

#parser.add_argument("--echo", "-e", action= "store_true",
#    help= """Just print what would be executed and exit.
#    
#""")

args= parser.parse_args()
print('')

def hostname2dir(hname):
    '''Convert hostname to a suitable directory name to use as top node of the
    backed up dirctory tree. E.g. myself@uk-cri-lcst01 will become uk-cri-lcst01
    
    hostname2dir('uk-cri-lcst01') ## 'uk-cri-lcst01'
    hostname2dir('berald01@uk-cri-lcst01') ## 'uk-cri-lcst01'
    hostname2dir('berald01@bal@uk-cri-lcst01') ## None
    '''
    dirname= hname.split('@')
    if len(dirname)  == 2:
        dirname= dirname[1]
    elif len(dirname)  == 1:
        dirname= dirname[0]
    else:
        dirname= None
    return(dirname)

## Make sure rootpath exists on server
# -----------------------------------------------------------------------------
cmd_rootexists= '''ssh %(server)s "find '%(rootpath)s' -maxdepth 0" ''' %{'server': args.server, 'rootpath': args.rootpath}
print(cmd_rootexists)
p= subprocess.Popen(cmd_rootexists, shell= True, stdout= subprocess.PIPE, stderr= subprocess.PIPE)
p= p.communicate()
if p[1] != '':
    sys.exit('Error while checking if directory %s exists: %s' %(args.rootpath, p[1]))
print('')
    
## Re-Create the source tree on the archive as QUARTER/SERVERNAME/ROOTHPATH
# ------------------------------------------------------------------------------
cmd_pquarter= "getArchiveDir.py --address '%s' --basepath '%s'" %(args.archive, args.archivePath)
print(cmd_pquarter)
p= subprocess.Popen(cmd_pquarter, shell= True, stdout= subprocess.PIPE, stderr= subprocess.PIPE)
pquarter= p.communicate()
if pquarter[1] != '':
    sys.exit('Error found while getting backup quarter: %s' %(pquarter[1]))
else:
    quarter= pquarter[0].strip()

topnode= hostname2dir(args.server)
if topnode is None:
    sys.exit('Unexpected format of server name %s' %(args.server))

archivePath= os.path.join(quarter, topnode) + args.rootpath
if not archivePath.endswith('/'):
    archivePath += os.sep
cmdArchCreateTree= '''ssh %(archive)s "mkdir -p '%(archivePath)s' "''' %{'archive': args.archive, 'archivePath': archivePath}
print(cmdArchCreateTree)

p= subprocess.Popen(cmdArchCreateTree, shell= True, stdout= subprocess.PIPE, stderr= subprocess.PIPE)
p= p.communicate()
if p[1] != '':
    sys.exit('Error found while creating backup directory: %s' %(p[1]))


## Create Log file
# -----------------------------------------------------------------------------
if args.log is None:
    logDir= os.path.join(args.rootpath, 'rsync_log', )
else:
    logDir= args.log
cmd_mklogdir= 'ssh %(server)s "mkdir -p %(logDir)s" ' %{'server': args.server, 'logDir': logDir}
print(cmd_mklogdir)
p= subprocess.Popen(cmd_mklogdir, shell= True, stdout= subprocess.PIPE, stderr= subprocess.PIPE)
p= p.communicate()
if p[1] != '':
    sys.exit('Error found while creating log directory: %s' %(p[1]))

now= datetime.datetime.now()
now= now.strftime("%Y%m%d-%H-%M-%S")
logfile= os.path.join(logDir, now + '.rsync.log')

## rsync
# -----------------------------------------------------------------------------

if args.exclude:
    exclude= []
    for x in args.exclude:
        exclude.append(" --exclude '" + x + "'")
    exclude= ''.join(exclude)
else:
    exclude= ''

if args.email:
    email= '''; cat %(logfile)s | mailx -s "rsync back up log" %(email)s ''' %{'logfile': logfile, 'email': args.email}
else:
    email= ''
print('')
if not args.rootpath.endswith('/'):
    args.rootpath += os.sep
cmd_rsync= '''ssh %(server)s "nohup rsync --stats --update --log-file='%(logfile)s' %(exclude)s -av '%(rootpath)s' '%(archive)s':'%(archivePath)s' %(email)s &"''' \
           %{'logfile': logfile, 'server':args.server, 'rootpath':args.rootpath, 'exclude': exclude, 'archive': args.archive, 'archivePath': archivePath, 'email': email}
print(cmd_rsync)

DEVNULL = open(os.devnull, 'wb')
p= subprocess.Popen(cmd_rsync, shell= True, stdout= DEVNULL, stderr= DEVNULL)
print('')
sys.exit()
